Micron Document
| SparkN0de-git | SparkN0de |


Displaying Raw • View renderedDownload


README.md v4.7.0-rc.2 (a20c7e1c) Text, 23.38 KB

Tc9d1d9# Reticulum MeshChatX

[Tff7b72Русский](Te6edf3lang/README.ru.md) | [Tff7b72Deutsch](Te6edf3lang/README.de.md) | [Tff7b72Italiano](Te6edf3lang/README.it.md) | [Tff7b72中文](Te6edf3lang/README.zh.md) | [Tff7b72日本語](Te6edf3lang/README.ja.md)

A extensively modified and feature-rich fork of [Tff7b72Reticulum MeshChat](Te6edf3https://github.com/liamcottle/reticulum-meshchat) by Liam Cottle.

This project is independent from the original Reticulum MeshChat project and is not affiliated with it.

Tff7b72- Website: [Tff7b72meshchatx.com](Te6edf3https://meshchatx.com)
Tff7b72- Source: [Tff7b72github.com/Quad4-Software/MeshChatX](Te6edf3https://github.com/Quad4-Software/MeshChatX)
Tff7b72- Mirror: [Tff7b72lavaforge.org/Reticulum-Things/MeshChatX](Te6edf3https://lavaforge.org/Reticulum-Things/MeshChatX)
Tff7b72- Releases: [Tff7b72github.com/Quad4-Software/MeshChatX](Te6edf3https://github.com/Quad4-Software/MeshChatX)
Tff7b72- Changelog: [Ta5d6ff`CHANGELOG.md`](CHANGELOG.md)
Tff7b72- Donate: [Ta5d6ff`donate.md`](donate.md) ([Donation](#donation))
Tff7b72- Umbrel App Store: [Tff7b72apps.umbrel.com/app/meshchatx](Te6edf3https://apps.umbrel.com/app/meshchatx)

<a href="https://apps.obtainium.imranr.dev/redirect.html?r=obtainium://add/https://github.com/Quad4-Software/MeshChatX"><img src="https://raw.githubusercontent.com/ImranR98/Obtainium/main/assets/graphics/badge_obtainium.png" height="60" alt="Get it on Obtainium"></a>

rngit NomadNet Node: Ta5d6ff`132f67e79d9b24aad014e93015fb858f:/page/index.mu`

rngit: Ta5d6ff`git clone rns://06a54b505bb67b25ef3f8097e8001edc/public/MeshChatX`

MeshChatX NomadNet Node: Ta5d6ff`c10d80b1a42fa958c37a6cc30dc04f53:/page/index.mu`

Tc9d1d9## Important Changes from Reticulum MeshChat

Tff7b72- Uses LXST for calls
Tff7b72- Replaced Peewee ORM with raw SQL.
Tff7b72- Replaced Axios with native fetch.
Tff7b72- Uses Electron 41.x (bundled Node 24 runtime).
Tff7b72- .whls ships with webserver and built-in frontend assets for more deployment options.
Tff7b72- i18n
Tff7b72- PNPM and UV for dependency management.

Tc9d1d9## Requirements

Tff7b72- Python Ta5d6ff`>=3.11` (from Ta5d6ff`pyproject.toml`)
Tff7b72- Node.js Ta5d6ff`>=24` (from Ta5d6ff`package.json` Ta5d6ff`engines`)
Tff7b72- pnpm Ta5d6ff`11.1.2` (from Ta5d6ff`package.json` Ta5d6ff`packageManager`)
Tff7b72- UV (used by Ta5d6ff`Taskfile.yml` and CI workflows)

**Browser Versions Required:**

Safari 16.4 or later, Chrome 111 or later, Firefox 128 or later (bundled web UI).

Ta5d6ff```Ta5d6ffbash
task install
task lint:all
task test:all
task build:all
Ta5d6ff```

Tc9d1d9## Install Methods

Use the method that matches your environment and packaging preference.

| Method | Includes frontend assets | Architectures | Best for |
| ----------------------- | ------------------------ | ------------------------------------------ | ---------------------------------------------- |
| Docker image | Yes | Ta5d6ff`linux/amd64`, Ta5d6ff`linux/arm64` | Fastest setup on Linux servers/hosts |
| Python wheel (Ta5d6ff`.whl`) | Yes | Any Python-supported architecture | Headless/web-server install without Node build |
| Linux AppImage | Yes | Ta5d6ff`x64`, Ta5d6ff`arm64` | Portable desktop use |
| Debian package (Ta5d6ff`.deb`) | Yes | Ta5d6ff`x64`, Ta5d6ff`arm64` | Debian/Ubuntu installs |
| RPM package (Ta5d6ff`.rpm`) | Yes | CI-runner dependent for published artifact | Fedora/RHEL/openSUSE style systems |
| From source | Built locally | Host architecture | Development and custom builds |

Notes:

Tff7b72- GitHub Actions builds tagged releases (Linux wheel/AppImage/deb/rpm, Windows, macOS, Flatpak, Android APKs when the tag is on Ta5d6ff`dev` or Ta5d6ff`master`, SLSA, draft release) in one run via Ta5d6ff`.github/workflows/build-release.yml`; the container image via Ta5d6ff`.github/workflows/docker.yml`. Branch and PR Android CI stays in Ta5d6ff`.github/workflows/android-build.yml`.
Tff7b72- Linux Ta5d6ff`x64` and Ta5d6ff`arm64` AppImage + DEB are built on GitHub; RPM is attempted and uploaded when produced.

Tc9d1d9## Docker

Tff7b72- **Docker Hub:** Ta5d6ff`quad4io/meshchatx`
Tff7b72- **GHCR:** Ta5d6ff`ghcr.io/quad4-software/meshchatx`

Ta5d6ff```Ta5d6ffbash
docker compose up -d
Ta5d6ff```

Ta5d6ff```Ta5d6ffbash
docker run -d --name reticulum-meshchatx Tffea00\
--restart unless-stopped Tffea00\
--security-opt no-new-privileges:true Tffea00\
-p T79c0ff127.0.0.1:8000:8000 Tffea00\
-v meshchatx-config:/config Tffea00\
ghcr.io/quad4-software/meshchatx:latest
Ta5d6ff```

You can substitute Ta5d6ff`quad4io/meshchatx:latest` for the image if you prefer Docker Hub.

Default compose file maps:

Tff7b72- Ta5d6ff`127.0.0.1:8000` on host -> container port Ta5d6ff`8000`
Tff7b72- Docker **named volume** Ta5d6ff`meshchatx-config` -> Ta5d6ff`/config` for persistence (works with the image Ta5d6ff`meshchat` user, UID 1000, without bind-mount permission fixes)

**Optional: bind mount a host directory instead**

If you want data under a host path (for example Ta5d6ff`./meshchat-config`), replace the volume line with Ta5d6ff`-v "$(pwd)/meshchat-config:/config"` (Compose: change the service Ta5d6ff`volumes` entry to that bind path). The container runs as **UID 1000**; the host directory must be writable by that uid (typical fix: Ta5d6ff`sudo chown -R 1000:1000 ./meshchat-config`). If the directory is empty on first run, create it first so Docker does not create it as root-only.

**Inspect or reset the named volume**

Ta5d6ff```Ta5d6ffbash
docker volume inspect meshchatx-config
T8b949e# remove container and delete persisted data (destructive)
docker rm -f reticulum-meshchatx
docker volume rm meshchatx-config
Ta5d6ff```

Tc9d1d9## Install from Release Artifacts

Tc9d1d9### 1) Linux AppImage (x64/arm64)

Tff7b721. Download Ta5d6ff`ReticulumMeshChatX-v<version>-linux-<arch>.AppImage` from releases.
Tff7b722. Make it executable and run:

Ta5d6ff```Ta5d6ffbash
chmod +x ./ReticulumMeshChatX-v*-linux-*.AppImage
./ReticulumMeshChatX-v*-linux-*.AppImage
Ta5d6ff```

Tc9d1d9### 2) Debian/Ubuntu `.deb` (x64/arm64)

Tff7b721. Download Ta5d6ff`ReticulumMeshChatX-v<version>-linux-<arch>.deb`.
Tff7b722. Install:

Ta5d6ff```Ta5d6ffbash
sudo apt install ./ReticulumMeshChatX-v*-linux-*.deb
Ta5d6ff```

Tc9d1d9### 3) RPM-based systems

Tff7b721. Download Ta5d6ff`ReticulumMeshChatX-v<version>-linux-<arch>.rpm` if present in the release.
Tff7b722. Install with your distro tool:

Ta5d6ff```Ta5d6ffbash
sudo rpm -Uvh ./ReticulumMeshChatX-v*-linux-*.rpm
Ta5d6ff```

Tc9d1d9### 4) Python wheel (`.whl`)

Release wheels include the built web assets.

Ta5d6ff```Ta5d6ffbash
pip install ./reticulum_meshchatx-*-py3-none-any.whl
meshchatx --headless
Ta5d6ff```

Ta5d6ff`pipx` is also supported:

Ta5d6ff```Ta5d6ffbash
pipx install ./reticulum_meshchatx-*-py3-none-any.whl
Ta5d6ff```

Tc9d1d9## Run from Source (Web Server Mode)

Use this when developing or when you need a local custom build.

Ta5d6ff```Ta5d6ffbash
git clone https://github.com/Quad4-Software/MeshChatX.git
Tffa657cd MeshChatX
corepack Tffa657enable
pnpm config Tffa657set verify-store-integrity Tffa657true
pnpm install --frozen-lockfile
pip install Ta5d6ff"uv==0.11.15"
uv lock --check
uv sync --group dev
pnpm run build-frontend
uv run python -m meshchatx.meshchat --headless --host T79c0ff127.0.0.1
Ta5d6ff```

Notes on the install commands above:

Tff7b72- Ta5d6ff`pnpm install --frozen-lockfile` refuses to update Ta5d6ff`pnpm-lock.yaml` and fails if the lockfile does not match Ta5d6ff`package.json`. This is what blocks an unexpected upstream version from being silently pulled in.
Tff7b72- Ta5d6ff`verify-store-integrity=true` is also set in the project Ta5d6ff`pnpm-workspace.yaml`; the explicit Ta5d6ff`pnpm config set` line above just hardens the user-level config too.
Tff7b72- Lifecycle scripts (Ta5d6ff`preinstall`/Ta5d6ff`postinstall`) are blocked by default in pnpm v11+. Only the packages listed under Ta5d6ff`allowBuilds` in Ta5d6ff`pnpm-workspace.yaml` are allowed to run install scripts (currently Ta5d6ff`electron`, Ta5d6ff`electron-winstaller`, Ta5d6ff`esbuild`).
Tff7b72- Ta5d6ff`uv lock --check` fails fast if Ta5d6ff`uv.lock` is out of sync with Ta5d6ff`pyproject.toml`; Ta5d6ff`uv sync` then resolves only from the lockfile.
Tff7b72- For a strict lockfile-only UV install (no implicit lockfile refresh), pin UV with Ta5d6ff`pip install "uv==0.11.15"` to match what CI uses.

If you intentionally want to update dependencies, run Ta5d6ff`pnpm update` / Ta5d6ff`uv lock` in a dedicated commit and review the resulting lockfile diff before pushing.

Tc9d1d9## Run sandboxed (Linux)

To run the native Ta5d6ff`meshchatx` binary (alias: Ta5d6ff`meshchat`) with extra filesystem isolation, you can use **Firejail** or **Bubblewrap** (Ta5d6ff`bwrap`) while keeping normal network access for Reticulum and the web UI. Full examples (pip/pipx, Poetry, USB serial notes) are in:

Tff7b72- [Ta5d6ff`docs/meshchatx_linux_sandbox.md`](docs/meshchatx_linux_sandbox.md)

The same page appears in the in-app **Documentation** list (MeshChatX docs) when served from the bundled or synced Ta5d6ff`meshchatx-docs` files.

Tc9d1d9## Linux desktop: emoji fonts

The emoji picker renders standard Unicode emoji using your system fonts (Electron/Chromium). If emoji show as empty squares (“tofu”), install a color emoji package and restart the app.

| Family (examples) | Package |
| -------------------------- | -------------------------------------------------------------------- |
| Arch Linux, Artix, Manjaro | Ta5d6ff`noto-fonts-emoji` (Ta5d6ff`sudo pacman -S noto-fonts-emoji`) |
| Debian, Ubuntu | Ta5d6ff`fonts-noto-color-emoji` (Ta5d6ff`sudo apt install fonts-noto-color-emoji`) |
| Fedora | Ta5d6ff`google-noto-emoji-color-fonts` |

After installing, run Ta5d6ff`fc-cache -fv` if glyphs still fail until the next login. Optional: Ta5d6ff`noto-fonts` for broader symbol coverage on minimal installs.

Tc9d1d9## Windows desktop: microphone (Electron, Windows 10 / 11)

Calls and voice attachments use the microphone through Chromium inside the desktop app. If the UI shows no access or **getUserMedia** fails, check **Windows privacy** first (this is a frequent cause for “classic” Win32 apps, including Electron):

Tff7b721. Press **Win + R**, paste **`ms-settings:privacy-microphone`**, press Enter.
Tff7b722. Turn **Microphone access** on.
Tff7b723. Enable **Let desktop apps access your microphone** (wording may vary slightly by Windows version).
Tff7b724. Ensure MeshChatX is not denied under **Choose which apps can access your microphone** if that list appears.

Also confirm the app is not muted in **Settings → System → Sound** and that a working input device is selected.

Tc9d1d9## Offline Builds

MeshChatX supports two levels of offline building:

Tff7b721. **Cached offline builds** — you already ran Ta5d6ff`make install` once and have Ta5d6ff`node_modules/`, Ta5d6ff`.venv/`, and local caches.
Tff7b722. **Air-gapped (zero-network) builds** — the machine has _never_ had internet. You create an offline bundle on a networked machine and transfer it.

Tc9d1d9### Cached Offline Builds

Set Ta5d6ff`MESHCHATX_OFFLINE_BUILD=1` before running any build command. This skips all network fetches (micron-parser-go WASM, Reticulum manual, repository wheels) and runs package managers in offline mode. If a required cached asset is missing, the build fails with a clear error instead of hanging.

Ta5d6ff```Ta5d6ffbash
T8b949e# Install dependencies offline (requires populated pnpm store and uv cache)
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 make install

T8b949e# Build frontend + backend offline
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 pnpm run build:offline

T8b949e# Build Linux desktop packages offline
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 pnpm run dist:linux:offline

T8b949e# Android Gradle also respects the flag
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 ./gradlew :app:assembleRelease
Ta5d6ff```

Tff7b72> **Note:** Cached offline mode only skips _build-time_ network access. The first `make install` must be run online (or with pre-populated caches) so that `pnpm` and `uv` have the packages available locally.

Tc9d1d9### Air-Gapped Builds (No Cache)

For machines with no internet access at all, create an offline bundle on a networked machine and transfer it.

**On the online machine:**

Ta5d6ff```Ta5d6ffbash
T8b949e# Create the bundle (includes node_modules, Python wheels, and tooling caches)
pnpm run bundle:offline

T8b949e# Optional: also pre-download packaging tools (appimagetool, etc.)
bash scripts/create-offline-bundle.sh --warm-packaging

T8b949e# Transfer the bundle to your air-gapped machine
tar czf meshchatx-offline-linux-x64.tar.gz -C vendor/offline meshchatx-offline-bundle-*/
Ta5d6ff```

**On the air-gapped machine:**

Ta5d6ff```Ta5d6ffbash
T8b949e# Extract the bundle into the project
tar xzf meshchatx-offline-linux-x64.tar.gz

T8b949e# Install from the bundle (extracts node_modules and sets up caches)
bash scripts/install-offline.sh

T8b949e# Build completely offline
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 make build

T8b949e# Or package offline
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 pnpm run dist:linux
Ta5d6ff```

The bundle is platform-specific because it contains native binaries (Electron, esbuild, etc.). Create it on the same OS/architecture as the air-gapped build host.

Prerequisites on the air-gapped machine: Ta5d6ff`node`, Ta5d6ff`pnpm`, Ta5d6ff`uv`, and Ta5d6ff`python3` must be installed (the bundle provides all dependencies and caches, not the toolchain itself).

Tff7b72> **Android builds:** The offline bundle does **not** include Android Chaquopy wheels. Build those separately on an online machine (`bash scripts/build-android-wheels-local.sh`) and copy `android/vendor/` to the air-gapped host alongside the project. Then run Gradle with `MESHCHATX_OFFLINE_BUILD=1`.

Tc9d1d9## Build Desktop Packages from Source

These scripts are defined in Ta5d6ff`package.json` and Ta5d6ff`Taskfile.yml`.

Tc9d1d9### Linux x64 AppImage + DEB

Ta5d6ff```Ta5d6ffbash
pnpm run dist:linux-x64
Ta5d6ff```

Tc9d1d9### Linux arm64 AppImage + DEB

Ta5d6ff```Ta5d6ffbash
pnpm run dist:linux-arm64
Ta5d6ff```

Tc9d1d9### RPM

Ta5d6ff```Ta5d6ffbash
pnpm run dist:rpm
Ta5d6ff```

Or through Task:

Ta5d6ff```Ta5d6ffbash
task dist:fe:rpm
Ta5d6ff```

Tc9d1d9## Container build (wheel, AppImage, deb, rpm)

Ta5d6ff`Dockerfile.build` runs the same shell-driven steps CI uses (Poetry, pnpm, Ta5d6ff`task`, packaging APT deps). It is oriented toward **linux/amd64** (NodeSource amd64 tarball, Task amd64 binary). Default target is everything; override with a build arg.

Targets for Ta5d6ff`MESHCHATX_BUILD_TARGETS`: Ta5d6ff`all` (default), Ta5d6ff`wheel`, or Ta5d6ff`electron` (AppImage + deb for x64 and arm64, best-effort RPM, no wheel).

Build:

Ta5d6ff```Ta5d6ffbash
docker build -f Dockerfile.build -t meshchatx-build:local .
Ta5d6ff```

Build only a wheel:

Ta5d6ff```Ta5d6ffbash
docker build -f Dockerfile.build --build-arg Te6edf3MESHCHATX_BUILD_TARGETSTff7b72=wheel -t meshchatx-build:wheel .
Ta5d6ff```

Copy Ta5d6ff`/artifacts` from the finished image to the host:

Ta5d6ff```Ta5d6ffbash
Te6edf3cidTff7b72=Tff7b72$(docker create meshchatx-build:localTff7b72)
docker cp Ta5d6ff"Tffd700${Te6edf3cidTffd700}Ta5d6ff:/artifactsTa5d6ff" ./meshchatx-artifacts
docker rm Ta5d6ff"Tffd700${Te6edf3cidTffd700}Ta5d6ff"
Ta5d6ff```

Tc9d1d9## Architecture Support Summary

Tff7b72- Docker image: Ta5d6ff`amd64`, Ta5d6ff`arm64`
Tff7b72- Linux AppImage: Ta5d6ff`x64`, Ta5d6ff`arm64`
Tff7b72- Linux DEB: Ta5d6ff`x64`, Ta5d6ff`arm64`
Tff7b72- Windows: Ta5d6ff`x64`, Ta5d6ff`arm64` (build scripts available)
Tff7b72- macOS: build scripts available (Ta5d6ff`arm64`, Ta5d6ff`universal`) for local build environments
Tff7b72- Android: universal APK only (see [Ta5d6ff`android/README.md`](android/README.md))

Tc9d1d9## Android

MeshChatX supports native Android APK builds (not only Termux).

Tc9d1d9### Build APKs from source

From repo root:

Ta5d6ff```Ta5d6ffbash
T8b949e# 1) Build Chaquopy wheels used by android/app/build.gradle
bash scripts/build-android-wheels-local.sh

T8b949e# 2) Build universal APKs (one debug + one release per run; see android/README.md)
Tffa657cd android
./gradlew --no-daemon :app:assembleDebug :app:assembleRelease
Ta5d6ff```

Offline Android builds are supported by setting Ta5d6ff`MESHCHATX_OFFLINE_BUILD=1`:

Ta5d6ff```Ta5d6ffbash
Te6edf3MESHCHATX_OFFLINE_BUILDTff7b72=T79c0ff1 ./gradlew --no-daemon :app:assembleRelease
Ta5d6ff```

This skips the repository wheels fetch step. The Ta5d6ff`android/vendor/` wheels and Ta5d6ff`meshchatx/public/repository-server-bundled/bundled/` must already be present.

There is a **single** Android variant. Gradle syncs the full Ta5d6ff`meshchatx/` tree into Ta5d6ff`app/src/main/python/meshchatx/`, including the offline repository wheel bundle. Published and documented builds use **universal** packaging only: one debug APK and one release APK per run, each containing the native ABIs configured in Ta5d6ff`android/app/build.gradle`.

Tff7b72- Debug: Ta5d6ff`android/app/build/outputs/apk/debug/app-debug.apk`
Tff7b72- Release: Ta5d6ff`android/app/build/outputs/apk/release/app-release-unsigned.apk`

Notes:

Tff7b72- Release outputs are unsigned by default unless you configure signing (Ta5d6ff`scripts/sign-android-apks.sh`).
Tff7b72- Native ABIs embedded in the universal APK follow Ta5d6ff`android/app/build.gradle` (including Ta5d6ff`armeabi-v7a` when enabled). Building wheels for Ta5d6ff`armeabi-v7a` needs an Android SDK on Ta5d6ff`ANDROID_HOME` (see Ta5d6ff`android/README.md`).
Tff7b72- If repo root Ta5d6ff`dist/reticulum_meshchatx-*.whl` exists (for example from Ta5d6ff`python -m build --wheel -o dist .`), bundled repository refresh prefers that wheel over PyPI for the MeshChatX package. CI builds that wheel before the Android Gradle step.

Additional docs:

Tff7b72- [Ta5d6ff`docs/meshchatx_on_android_with_termux.md`](docs/meshchatx_on_android_with_termux.md)
Tff7b72- [Ta5d6ff`android/README.md`](android/README.md)

Tc9d1d9## Configuration

MeshChatX supports both CLI args and env vars.

| Argument | Environment Variable | Default | Description |
| -------------------------- | ---------------------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ta5d6ff`--host` | Ta5d6ff`MESHCHAT_HOST` | Ta5d6ff`127.0.0.1` | Web server bind address |
| Ta5d6ff`--port` | Ta5d6ff`MESHCHAT_PORT` | Ta5d6ff`8000` | Web server port |
| Ta5d6ff`--no-https` | Ta5d6ff`MESHCHAT_NO_HTTPS` | Ta5d6ff`false` | Disable HTTPS |
| Ta5d6ff`--ssl-cert` / Ta5d6ff`--ssl-key` | Ta5d6ff`MESHCHAT_SSL_CERT` / Ta5d6ff`MESHCHAT_SSL_KEY` | (none) | PEM certificate and private key paths; both must be set together. Overrides auto-generated certs under the identity Ta5d6ff`ssl/` directory. |
| Ta5d6ff`--rns-log-level` | Ta5d6ff`MESHCHAT_RNS_LOG_LEVEL` | (none) | Reticulum (RNS) stack log level: Ta5d6ff`none`, Ta5d6ff`critical`, Ta5d6ff`error`, Ta5d6ff`warning`, Ta5d6ff`notice`, Ta5d6ff`verbose`, Ta5d6ff`debug`, Ta5d6ff`extreme`, or a numeric level. CLI overrides env when both are set. |
| Ta5d6ff`--headless` | Ta5d6ff`MESHCHAT_HEADLESS` | Ta5d6ff`false` | Do not auto-launch browser |
| Ta5d6ff`--auth` | Ta5d6ff`MESHCHAT_AUTH` | Ta5d6ff`false` | Enable basic auth |
| Ta5d6ff`--reset-password` | Ta5d6ff`MESHCHAT_RESET_PASSWORD` | Ta5d6ff`false` | Clear the stored password hash so a new password can be set via the web UI |
| Ta5d6ff`--storage-dir` | Ta5d6ff`MESHCHAT_STORAGE_DIR` | Ta5d6ff`./storage` | Data directory |
| Ta5d6ff`--public-dir` | Ta5d6ff`MESHCHAT_PUBLIC_DIR` | auto/bundled | Frontend files directory (needed for source installs without bundled assets) |

Tc9d1d9## Branches

| Branch | Purpose |
| -------- | --------------------------------------------------------------- |
| Ta5d6ff`master` | Stable releases. Production-ready code only. |
| Ta5d6ff`dev` | Active development. May contain breaking or incomplete changes. |

Tc9d1d9## Development

Common tasks from Ta5d6ff`Taskfile.yml`:

Ta5d6ff```Ta5d6ffbash
task install
task lint:all
task test:all
task build:all
Ta5d6ff```

Ta5d6ff`Makefile` shortcuts are also available:

| Command | Description |
| -------------- | --------------------------------------- |
| Ta5d6ff`make install` | Install pnpm and UV dependencies |
| Ta5d6ff`make run` | Run MeshChatX via UV |
| Ta5d6ff`make build` | Build frontend |
| Ta5d6ff`make lint` | Run eslint and ruff |
| Ta5d6ff`make test` | Run frontend and backend tests |
| Ta5d6ff`make clean` | Remove build artifacts and node_modules |

Tc9d1d9## Versioning

Current version in this repo is Ta5d6ff`4.7.0`.

Tff7b72- **`package.json`** Ta5d6ff`version` is the only value you edit for a release bump.
Tff7b72- Run **`pnpm run version:sync`** (also run at the start of **`pnpm run build`**) to propagate that version into **`pyproject.toml`**, **`meshchatx/src/version.py`**, **`THIRD_PARTY_NOTICES.txt`** (product line), **README** / **lang/README.\*** “current version” lines, **`docs/meshchatx_on_raspberry_pi.md`** pipx example, and **`packaging/arch/PKGBUILD`** helpers.
Tff7b72- **`meshchatx.__version__`** is read from **`meshchatx/src/version.py`** without importing **`meshchatx.src`**, so a plain Ta5d6ff`import meshchatx` stays lightweight.
Tff7b72- **Changelog** entries stay manual when you cut a release.

Tc9d1d9## Security

Security and integrity details:

Tff7b72- [Ta5d6ff`SECURITY.md`](SECURITY.md)
Tff7b72- [Ta5d6ff`LEGAL.md`](LEGAL.md)
Tff7b72- Built-in integrity checks and HTTPS/WSS defaults in app runtime.
Tff7b72- CI and release builds on GitHub Actions.

Tc9d1d9## Adding a Language

My workflow: ArgosTranslate -> Local LLM (Qwen 3 + Gemma 4)

People are then welcome to submit fixes to me via LXMF or wherever you can contact me.

Locale discovery is automatic. Add a new file under Ta5d6ff`meshchatx/src/frontend/locales/` (for example Ta5d6ff`xx.json`) with the same keys as Ta5d6ff`en.json` and a top-level Ta5d6ff`_languageName` string for the label shown in the language selector. You can copy Ta5d6ff`en.json` and translate every value by hand; **machine-assisted generation is optional** and never required.

**Optional: Argos Translate bootstrap** -- If you want a machine-generated first draft from Ta5d6ff`en.json`, you can use Ta5d6ff`scripts/argos_translate.py`. It handles formatting, color output, and helps protect interpolation variables (like Ta5d6ff`{count}`) from accidental edits.

Ta5d6ff```Ta5d6ffbash
T8b949e# Install argostranslate if you haven't already
pipx install argostranslate

T8b949e# Run the translation script
python scripts/argos_translate.py --from en --to xx --input meshchatx/src/frontend/locales/en.json --output meshchatx/src/frontend/locales/xx.json --name Ta5d6ff"Your Language Name"
Ta5d6ff```

After any machine-assisted pass, have an LLM or a human reviewer verify grammar, context, and tone (for example formal vs informal).

Run Ta5d6ff`pnpm test -- tests/frontend/i18n.test.js --run` to verify key parity with Ta5d6ff`en.json`.

No other code changes are required. The app, language selector, and tests all discover locales from the Ta5d6ff`meshchatx/src/frontend/locales/` directory at build time.

Tc9d1d9## Donation

Donations are voluntary. They help fund time and effort to develop this app.

**Ways to give:** [Ta5d6ff`donate.md`](donate.md) (Monero, Ko-Fi, Buy Me a Coffee).

Tc9d1d9## Credits

Tff7b72- [Tff7b72Liam Cottle](Te6edf3https://github.com/liamcottle) - Original Reticulum MeshChat
Tff7b72- [Tff7b72RFnexus](Te6edf3https://github.com/RFnexus) - micron parser JavaScript work
Tff7b72- [Tff7b72markqvist](Te6edf3https://github.com/markqvist) - Reticulum, LXMF, LXST

Tc9d1d9## License

Project-owned portions are licensed under 0BSD.
Original upstream portions from Reticulum MeshChat remain under MIT.
See [Ta5d6ff`LICENSE`](LICENSE) for full text and notices.


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────